home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / tcpip / amiga / asrc29p.lha / tcpsubr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  6.9 KB  |  317 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "mbuf.h"
  5. #include "netuser.h"
  6. #include "internet.h"
  7. #include "tcp.h"
  8. #include "ip.h"
  9.  
  10. static int16 hash_tcb __ARGS((struct connection *conn));
  11.  
  12. /* TCP connection states */
  13. char *Tcpstates[] = {
  14.     "",
  15.     "Closed",
  16.     "Listen",
  17.     "SYN sent",
  18.     "SYN received",
  19.     "Established",
  20.     "FIN wait 1",
  21.     "FIN wait 2",
  22.     "Close wait",
  23.     "Last ACK",
  24.     "Closing",
  25.     "Time wait"
  26. };
  27.  
  28. /* TCP closing reasons */
  29. char *Tcpreasons[] = {
  30.     "Normal",
  31.     "Reset/Refused",
  32.     "Timeout",
  33.     "ICMP"
  34. };
  35. struct tcb *Tcbs[NTCB];
  36. int16 Tcp_mss = DEF_MSS;    /* Maximum segment size to be sent with SYN */
  37. int32 Tcp_irtt = DEF_RTT;    /* Initial guess at round trip time */
  38. int Tcp_retry = DEF_RETRIES;    /* Max retries before resetting tcb */
  39. int Tcp_trace;            /* State change tracing flag */
  40. struct tcp_rtt Tcp_rtt[RTTCACHE];
  41. struct mib_entry Tcp_mib[] = {
  42.     NULLCHAR,        0,
  43.     "tcpRtoAlgorithm",    4,    /* Van Jacobsen's algorithm */
  44.     "tcpRtoMin",        MSPTICK,    /* No lower bound */
  45.     "tcpRtoMax",        MAXINT32,    /* No upper bound */
  46.     "tcpMaxConn",        -1L,    /* No limit */
  47.     "tcpActiveOpens",    0,
  48.     "tcpPassiveOpens",    0,
  49.     "tcpAttemptFails",    0,
  50.     "tcpEstabResets",    0,
  51.     "tcpCurrEstab",        0,
  52.     "tcpInSegs",        0,
  53.     "tcpOutSegs",        0,
  54.     "tcpRetransSegs",    0,
  55.     NULLCHAR,        0,    /* Connection state goes here */
  56.     "tcpInErrs",        0,
  57.     "tcpOutRsts",        0,
  58.     "tcpChkSumErrs",    0,
  59. };
  60.  
  61.  
  62. /* Lookup connection, return TCB pointer or NULLTCB if nonexistant */
  63. struct tcb *
  64. lookup_tcb(conn)
  65. struct connection *conn;
  66. {
  67.     register struct tcb *tcb;
  68.  
  69.     tcb = Tcbs[hash_tcb(conn)];
  70.     while(tcb != NULLTCB){
  71.         /* Yet another structure compatibility hack */
  72.         if(conn->local.address == tcb->conn.local.address
  73.          && conn->remote.address == tcb->conn.remote.address
  74.          && conn->local.port == tcb->conn.local.port
  75.          && conn->remote.port == tcb->conn.remote.port)
  76.             break;
  77.         tcb = tcb->next;
  78.     }
  79.     return tcb;
  80. }
  81.  
  82. /* Create a TCB, return pointer. Return pointer if TCB already exists. */
  83. struct tcb *
  84. create_tcb(conn)
  85. struct connection *conn;
  86. {
  87.     register struct tcb *tcb;
  88.     struct tcp_rtt *tp;
  89.  
  90.     if((tcb = lookup_tcb(conn)) != NULLTCB)
  91.         return tcb;
  92.     tcb = (struct tcb *)callocw(1,sizeof (struct tcb));
  93.     ASSIGN(tcb->conn,*conn);
  94.  
  95.     tcb->state = TCP_CLOSED;
  96.     tcb->cwind = tcb->mss = Tcp_mss;
  97.     tcb->ssthresh = 65535;
  98.     if((tp = rtt_get(tcb->conn.remote.address)) != NULLRTT){
  99.         tcb->srtt = tp->srtt;
  100.         tcb->mdev = tp->mdev;
  101.     } else {
  102.         tcb->srtt = Tcp_irtt;    /* mdev = 0 */
  103.     }
  104.     /* Initialize timer intervals */
  105.     tcb->timer.start = tcb->srtt / MSPTICK;
  106.     tcb->timer.func = tcp_timeout;
  107.     tcb->timer.arg = tcb;
  108.  
  109.     link_tcb(tcb);
  110.     return tcb;
  111. }
  112.  
  113. /* Close our TCB */
  114. void
  115. close_self(tcb,reason)
  116. register struct tcb *tcb;
  117. int reason;
  118. {
  119.     struct reseq *rp1;
  120.     register struct reseq *rp;
  121.  
  122.     if(tcb == NULLTCB)
  123.         return;
  124.  
  125.     stop_timer(&tcb->timer);
  126.     tcb->reason = reason;
  127.  
  128.     /* Flush reassembly queue; nothing more can arrive */
  129.     for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  130.         rp1 = rp->next;
  131.         free_p(rp->bp);
  132.         free((char *)rp);
  133.     }
  134.     tcb->reseq = NULLRESEQ;
  135.     setstate(tcb,TCP_CLOSED);
  136. }
  137.  
  138. /* Sequence number comparisons
  139.  * Return true if x is between low and high inclusive,
  140.  * false otherwise
  141.  */
  142. int
  143. seq_within(x,low,high)
  144. register int32 x,low,high;
  145. {
  146.     if(low <= high){
  147.         if(low <= x && x <= high)
  148.             return 1;
  149.     } else {
  150.         if(low >= x && x >= high)
  151.             return 1;
  152.     }
  153.     return 0;
  154. }
  155. int
  156. seq_lt(x,y)
  157. register int32 x,y;
  158. {
  159.     return (long)(x-y) < 0;
  160. }
  161. #ifdef    notdef
  162. int
  163. seq_le(x,y)
  164. register int32 x,y;
  165. {
  166.     return (long)(x-y) <= 0;
  167. }
  168. #endif    /* notdef */
  169. int
  170. seq_gt(x,y)
  171. register int32 x,y;
  172. {
  173.     return (long)(x-y) > 0;
  174. }
  175. int
  176. seq_ge(x,y)
  177. register int32 x,y;
  178. {
  179.     return (long)(x-y) >= 0;
  180. }
  181.  
  182. /* Hash a connect structure into the hash chain header array */
  183. static int16
  184. hash_tcb(conn)
  185. struct connection *conn;
  186. {
  187.     register int16 hval;
  188.  
  189.     /* Compute hash function on connection structure */
  190.     hval = hiword(conn->remote.address);
  191.     hval ^= loword(conn->remote.address);
  192. #ifdef    notdef    /* Never changes, so not really needed */
  193.     hval ^= hiword(conn->local.address);
  194.     hval ^= loword(conn->local.address);
  195. #endif
  196.     hval ^= conn->remote.port;
  197.     hval ^= conn->local.port;
  198.     return (int16)(hval % NTCB);
  199. }
  200. /* Insert TCB at head of proper hash chain */
  201. void
  202. link_tcb(tcb)
  203. register struct tcb *tcb;
  204. {
  205.     register struct tcb **tcbhead;
  206.  
  207.     tcb->prev = NULLTCB;
  208.     tcbhead = &Tcbs[hash_tcb(&tcb->conn)];
  209.     tcb->next = *tcbhead;
  210.     if(tcb->next != NULLTCB)
  211.         tcb->next->prev = tcb;
  212.  
  213.     *tcbhead = tcb;
  214. }
  215. /* Remove TCB from whatever hash chain it may be on */
  216. void
  217. unlink_tcb(tcb)
  218. register struct tcb *tcb;
  219. {
  220.     register struct tcb **tcbhead;
  221.  
  222.     tcbhead = &Tcbs[hash_tcb(&tcb->conn)];
  223.     if(tcb->prev == NULLTCB)
  224.         *tcbhead = tcb->next;    /* We're the first one on the chain */
  225.     else
  226.         tcb->prev->next = tcb->next;
  227.     if(tcb->next != NULLTCB)
  228.         tcb->next->prev = tcb->prev;
  229. }
  230. void
  231. setstate(tcb,newstate)
  232. register struct tcb *tcb;
  233. register int newstate;
  234. {
  235.     register char oldstate;
  236.  
  237.     oldstate = tcb->state;
  238.     tcb->state = newstate;
  239.     if(Tcp_trace)
  240.         printf("TCB %lx %s -> %s\n",ptol(tcb),
  241.          Tcpstates[oldstate],Tcpstates[newstate]);
  242.  
  243.     /* Update MIB variables */
  244.     if(oldstate == TCP_CLOSED && newstate == TCP_SYN_SENT)
  245.         tcpActiveOpens++;
  246.     else if(oldstate == TCP_LISTEN && newstate == TCP_SYN_RECEIVED)
  247.         tcpPassiveOpens++;
  248.     else if((oldstate == TCP_SYN_SENT || oldstate == TCP_SYN_RECEIVED)
  249.      && newstate == TCP_CLOSED)
  250.         tcpAttemptFails++; 
  251.     else if(oldstate == TCP_SYN_RECEIVED && newstate == TCP_LISTEN)
  252.         tcpAttemptFails++; 
  253.     else if((oldstate == TCP_ESTABLISHED || oldstate == TCP_CLOSE_WAIT)
  254.      && newstate == TCP_CLOSED)
  255.         tcpEstabResets++;
  256.  
  257.     if(oldstate == TCP_ESTABLISHED || oldstate == TCP_CLOSE_WAIT)
  258.         tcpCurrEstab--;
  259.  
  260.     if(newstate == TCP_ESTABLISHED || newstate == TCP_CLOSE_WAIT)
  261.         tcpCurrEstab++;
  262.  
  263.     if(tcb->s_upcall)
  264.         (*tcb->s_upcall)(tcb,oldstate,newstate);
  265.  
  266.     switch(newstate){
  267.     case TCP_ESTABLISHED:
  268.         /* Notify the user that he can begin sending data */
  269.         if(tcb->t_upcall)
  270.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  271.         break;
  272.     }
  273. }
  274. /* Round trip timing cache routines.
  275.  * These functions implement a very simple system for keeping track of
  276.  * network performance for future use in new connections.
  277.  * The emphasis here is on speed of update (rather than optimum cache hit
  278.  * ratio) since rtt_add is called every time a TCP connection updates
  279.  * its round trip estimate.
  280.  */
  281. void
  282. rtt_add(addr,rtt)
  283. int32 addr;        /* Destination IP address */
  284. int32 rtt;
  285. {
  286.     register struct tcp_rtt *tp;
  287.     int32 abserr;
  288.  
  289.     if(addr == 0)
  290.         return;
  291.     tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  292.     if(tp->addr != addr){
  293.         /* New entry */
  294.         tp->addr = addr;
  295.         tp->srtt = rtt;
  296.         tp->mdev = 0;
  297.     } else {
  298.         /* Run our own SRTT and MDEV integrators, with rounding */
  299.         abserr = (rtt > tp->srtt) ? rtt - tp->srtt : tp->srtt - rtt;
  300.         tp->srtt = ((AGAIN-1)*tp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
  301.         tp->mdev = ((DGAIN-1)*tp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
  302.     }
  303. }
  304. struct tcp_rtt *
  305. rtt_get(addr)
  306. int32 addr;
  307. {
  308.     register struct tcp_rtt *tp;
  309.  
  310.     if(addr == 0)
  311.         return NULLRTT;
  312.     tp = &Tcp_rtt[(unsigned short)addr % RTTCACHE];
  313.     if(tp->addr != addr)
  314.         return NULLRTT;
  315.     return tp;
  316. }
  317.